/**
 * @(#)RollbackTransaccionFake.java Nov 5, 2006
 *
 * Copyright (c) 2005-2010 Psiqueware S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information Psiqueware S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * <br/>Usuario : AngelElectrico
 * <br/>Creaci&oacute;n: Nov 5, 2006 - 9:24:47 PM
 * <br/>
 * <br/>
 * <br/><t5>Cambios :</t5>
 * <br/><b>Fecha | Autor  |  Cambios</b>
 * <ul>
 * <li>Nov 5, 2006 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 * <li>Nov 6, 2006 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Se le a&ntilde;ade la clonacion de cada argumento de la lista original.</li>
 * </ul>
 */

package com.psiqueware.alheli.dao.fake;

import com.psiqueware.alheli.logging.Logger;
import com.psiqueware.alheli.logging.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * En esta clase almacenamos la informacion para poder deshacer una trasaccion fake.
 * <br/>Paquete Original: com.psiqueware.basico.dao.fake
 * <br/>Nombre  Original: RollbackTransaccionFake
 * <br/>Oprima para ver : <a href="RollbackTransaccionFake.java.html"><i>C&oacute;digo Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a>
 * @version Revision: 1.1 Nov 5, 2006 9:24:47 PM
 * @noinspection ClassWithoutToString, DuplicateStringLiteralInspection
 */
public final class RollbackTransaccionFake
{

    /**
     * Logger de clase para RollbackTransaccionFake
     */
    private static final Logger log = LoggerFactory.getLogger(RollbackTransaccionFake.class);

    /**
     * Lista con la informacion original.
     */
    private List m_original;

    /**
     * Instancia de la {@link List} que se esta cambiando.
     */
    private List m_listaCambios;

    /**
     * Lista con los cambios por update.
     */
    private List m_updates = new ArrayList();

    /**
     * Constructor de RollbackTransaccionFake.
     */
    public RollbackTransaccionFake()
    {
    }

    /**
     * Establece una lista previa a cualquier cambio.
     *
     * @param original listado con los objetos como se encontraba antes de los cambios.
     *
     * @noinspection unchecked, ObjectEquality
     */
    public void setListOriginal(List<?> original)
    {   /**
     if ( null == m_original )
     {
     m_original = new ArrayList ();
     for ( Object o : original )
     {
     Object clonado = RefleccionClases.cloneMe ( o );
     m_original.add ( clonado );
     }
     m_listaCambios = original;
     }

     if ( m_listaCambios != null && m_listaCambios != original )
     {
     String error = "<error>La lista almacenada no es la misma que la que se pretende almacenar.</error>";
     log.error ( error );
     throw new IllegalArgumentException ( error );
     } **/
    }

    /**
     * Regresa al estado anterior esta transaccion.
     *
     * @noinspection unchecked, CastToConcreteClass
     */
    public void rollback()
    {
        m_listaCambios.clear();
        m_listaCambios.addAll(m_original);

        for (int i = m_updates.size() - 1; i == 0; i++)
        {
            TransaccionUpdate transaccionUpdate = (TransaccionUpdate) m_listaCambios.get(i);
            transaccionUpdate.rollbackUpdateValor();
        }
        m_updates.clear();
    }

    /**
     * invoquese cadavez que se quiera realizar una actualizacion a un valor en un bean.
     *
     * @param instanciaClase bean donde se va a realizar el cambio.
     * @param nombreAtributo nombre del atributo a cambiar.
     * @param nuevoValor     nuevo valor a establecer.
     *
     * @noinspection NonBooleanMethodNameMayNotStartWithQuestion, unchecked
     */
    public void addUpdateValor(Object instanciaClase, String nombreAtributo, Object nuevoValor)
    {/*
        try
        {
            //Obtenemos el valor anterior.
            Object valorAnterior = RefleccionMetodos.ejecutaFuncionGetter ( instanciaClase, nombreAtributo );
            //Establecemos el nuevo valor.
            RefleccionMetodos.ejecutaMetodoSetter ( instanciaClase, nuevoValor, nombreAtributo );
            TransaccionUpdate update = new TransaccionUpdate ();
            update.setInstanciaClase ( instanciaClase );
            update.setNombreAtributo ( nombreAtributo );
            update.setValorAnterior ( valorAnterior );
            m_updates.add ( update );
        }
        catch ( NoSuchMethodException e )
        {
            String error = "<error>No se encontro el metodo a actualizar el atributo " + nombreAtributo + ".</error>";
            log.error ( error );
            log.error ( e );
            throw new RuntimeException ( error, e );

        }
        catch ( IllegalAccessException e )
        {
            String error = "<error>No se pudo acceder a los metodos para " + nombreAtributo + "</error>";
            log.error ( error );
            log.error ( e );
            throw new RuntimeException ( error, e );

        }
        catch ( InvocationTargetException e )
        {
            String error = "<error>Uno de los metodos para actualizar el atributo solto una excepcion.</error>";
            log.error ( error );
            log.error ( e );
            throw new RuntimeException ( error, e );

        } */

    }

    /**
     * Almacena un update para cada cambio.
     *
     * @noinspection ClassWithoutConstructor, ClassWithoutToString, NonStaticInnerClassInSecureContext
     */
    private class TransaccionUpdate
    {

        /**
         * Instancia del VO a modificar.
         */
        private Object m_instanciaClase;

        /**
         * Nombre del atributo modificado.
         */
        private String m_nombreAtributo;

        /**
         * Valor anterior.
         */
        private Object m_valorAnterior;


        /**
         * Hace un rollback de este update.
         */
        public void rollbackUpdateValor()
        {   /**
         try
         {
         //Establecemos el nuevo valor.
         RefleccionMetodos.ejecutaMetodoSetter ( m_instanciaClase, m_valorAnterior, m_nombreAtributo );
         }
         catch ( NoSuchMethodException e )
         {
         String error = "<error>No se encontro el metodo a actualizar el atributo " + m_nombreAtributo + ".</error>";
         log.error ( error );
         log.error ( e );
         throw new RuntimeException ( error, e );

         }
         catch ( IllegalAccessException e )
         {
         String error = "<error>No se pudo acceder a los metodos para " + m_nombreAtributo + "</error>";
         log.error ( error );
         log.error ( e );
         throw new RuntimeException ( error, e );

         }
         catch ( InvocationTargetException e )
         {
         String error = "<error>Uno de los metodos para actualizar el atributo solto una excepcion.</error>";
         log.error ( error );
         log.error ( e );
         throw new RuntimeException ( error, e );

         } **/

        }

        /**
         * Devuelve el Instancia del VO a modificar.
         *
         * @return valor de 'instanciaClase'.
         *
         * @see Object
         */
        public Object getInstanciaClase()
        {
            return m_instanciaClase;
        }

        /**
         * Establece el Instancia del VO a modificar.
         *
         * @param instanciaClase nuevo valor para 'instanciaClase'.
         *
         * @see Object
         */
        public void setInstanciaClase(Object instanciaClase)
        {
            this.m_instanciaClase = instanciaClase;
        }

        /**
         * Devuelve el Nombre del atributo modificado.
         *
         * @return valor de 'nombreAtributo'.
         *
         * @see String
         */
        public String getNombreAtributo()
        {
            return m_nombreAtributo;
        }

        /**
         * Establece el Nombre del atributo modificado.
         *
         * @param nombreAtributo nuevo valor para 'nombreAtributo'.
         *
         * @see String
         */
        public void setNombreAtributo(String nombreAtributo)
        {
            this.m_nombreAtributo = nombreAtributo;
        }

        /**
         * Devuelve el Valor anterior.
         *
         * @return valor de 'valorAnterior'.
         *
         * @see Object
         */
        public Object getValorAnterior()
        {
            return m_valorAnterior;
        }

        /**
         * Establece el Valor anterior.
         *
         * @param valorAnterior nuevo valor para 'valorAnterior'.
         *
         * @see Object
         */
        public void setValorAnterior(Object valorAnterior)
        {
            this.m_valorAnterior = valorAnterior;
        }
    }


}

